#include "stdafx.h"
#include "Bincode.h"
#include "constants.h"
#include "cstdlib"


auto convert = [](std::string origin, int width) -> std::string {
  char out[27], nums[27];
  int num = 0;
  auto to_int = [](auto origin) -> auto { return stoi(origin); };
  num = (origin[0] != '$')
            ? to_int(origin)
            : to_int(origin.substr(2)) +
                  ((origin[1] == 's')
                       ? 16
                       : (origin[1] == 't') ? 8 : -to_int(origin.substr(2)));
  _itoa_s(num, nums, 2);
  auto pattern = "%0" + std::to_string(width) + "s";
  sprintf_s(out, pattern.c_str(), nums);
  std::string ret(out);
  return ret;
};
Bincode::Bincode(std::string line) {
  std::string ret;
  auto words = splitList(line, " ");
  auto operation = words[0];
  auto operands = words[1];
  auto operand = splitList(operands, ",");
  if (operand.size() == 3) {
    auto rd = operand[0];
    auto rs = operand[1];
    auto rt = operand[2];
    std::string shamnt = "0";
    if (rt[0] != '$' && rStyle.find(operation) != rStyle.end()) {
      shamnt = rt;
      rt = rd;
      rs = "0";
    }
    if (rStyle.find(operation) != rStyle.end())
      ret = rStyle[operation].substr(0, 6) + convert(rs, 5) + convert(rt, 5) +
            convert(rd, 5) + convert(shamnt, 5) + rStyle[operation].substr(6);
    else
      ret =
          iStyle[operation] + convert(rd, 5) + convert(rs, 5) + convert(rt, 16);
  } else if (operand.size() == 1) {
    auto address = operand[0];
    ret = iStyle[operation] + convert(address, 26);
  } else if (operand.size() == 2) {
    auto rs = operand[0];
    auto words = splitList(operand[1], "(");
    auto address = words[0];
    words = splitList(words[1], ")");
    auto rt = words[0];
    ret = iStyle[operation] + convert(rs, 5) + convert(rt, 5) +
          convert(address, 16);
  }
  bincode = ret;
}

std::string Bincode::origin() { return bincode; }

std::string Bincode::type1() {
  return bincode.substr(0, 8) + " " + bincode.substr(8, 8) + " " +
         bincode.substr(16, 8) + " " + bincode.substr(24);
}

std::string Bincode::type2() {
  return bincode.substr(0, 6) + " " + bincode.substr(6, 5) + " " +
         bincode.substr(11, 5) + " " + bincode.substr(16, 5) + " " +
         bincode.substr(21, 5) + " " + bincode.substr(26);
}

Bincode::~Bincode() {}
